package marchsoft.modules.tiku.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.RequiredArgsConstructor;
import marchsoft.base.BasicServiceImpl;
import marchsoft.enums.DataScopeEnum;
import marchsoft.enums.ResultEnum;
import marchsoft.exception.BadRequestException;
import marchsoft.modules.system.entity.Dept;
import marchsoft.modules.system.mapper.DeptMapper;
import marchsoft.modules.tiku.entity.dto.StudentDto;
import marchsoft.modules.tiku.entity.dto.StudentExcel;
import marchsoft.modules.tiku.entity.EStudent;
import marchsoft.modules.tiku.entity.dto.EStudentQueryCriteria;
import marchsoft.modules.tiku.mapper.EStudentMapper;
import marchsoft.modules.tiku.service.IEStudentService;
import marchsoft.modules.tiku.service.mapstruct.StudentMapStruct;
import marchsoft.utils.FileUtils;
import marchsoft.utils.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 学生基本信息表 服务实现类
 * </p>
 *
 * @author wjy
 * @since 2022-03-29
 */


@Service
@RequiredArgsConstructor
public class EStudentServiceImpl extends BasicServiceImpl<EStudentMapper, EStudent> implements IEStudentService {

    private final EStudentMapper eStudentMapper;
    private final DeptMapper deptMapper;
    private final StudentMapStruct studentMapStruct;


    @Override
    public Long findStudentIdByStudentNumAndDeptId(String username, Long deptId) {
        LambdaQueryWrapper<EStudent> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EStudent::getStudentNum,username).eq(EStudent::getUniversityId,deptId);
        EStudent eStudent = this.getOne(queryWrapper);
        if (ObjectUtil.isNull(eStudent)) {
            throw new BadRequestException(ResultEnum.USER_NOT_EXIST);
        }

        return eStudent.getId();
    }

    @Override
    public IPage<StudentDto> findStudent(IPage<EStudent> buildPage, EStudentQueryCriteria criteria) {
        return eStudentMapper.selectAllStudents(buildPage,buildEStudentCriteria(criteria));
    }

    @Override
    public void addStudent(EStudent studentDTO) {
        int i = eStudentMapper.insert(studentDTO);
        if (i < 1) {
            throw new BadRequestException(ResultEnum.INSERT_OPERATION_FAIL);
        }
    }

    @Override
    public void updateOrCreateStudent(EStudent studentDTO) {
        if (ObjectUtil.isNull(studentDTO.getUniversityId())) {
            throw new BadRequestException(ResultEnum.PARAM_IS_BLANK);
        }
        // 判断该部门id是否为顶级部门（存在）
        Long universityId = studentDTO.getUniversityId();
        Dept dept = deptMapper.selectOne(new LambdaQueryWrapper<Dept>().eq(Dept::getId, universityId).eq(Dept::getPid, 0));
        if (ObjectUtil.isNull(dept)) {
            throw new BadRequestException(ResultEnum.DEPT_NOT_EXIST);
        }
        // 前台用户登陆时，以学号和部门作为唯一标识。验证是否修改学号，若修改学号的话，判断新学号是否已存在。
        EStudent eStudent = new EStudent();
        if (ObjectUtil.isNotNull(studentDTO.getId())) {
            eStudent = eStudentMapper.selectById(studentDTO.getId());
        }

        if (ObjectUtil.isNull(studentDTO.getId()) || (! eStudent.getStudentNum().equals(studentDTO.getStudentNum())) || (!eStudent.getUniversityId().equals(studentDTO.getUniversityId())) ) {
            // 修改了学号，判断是否重复
            EStudent eStudent1 = eStudentMapper.selectOne(new LambdaQueryWrapper<EStudent>().eq(EStudent::getStudentNum, studentDTO.getStudentNum()).eq(EStudent::getUniversityId, studentDTO.getUniversityId()));
            if (ObjectUtil.isNotNull(eStudent1)) {
                throw new BadRequestException(ResultEnum.STUDENT_EXIST);
            }
        }

        this.saveOrUpdate(studentDTO);
    }

    /**
     * 条件构造器  查询条件
     *
     * @param criteria
     * @return
     */
    private QueryWrapper<EStudent> buildEStudentCriteria(EStudentQueryCriteria criteria) {
        QueryWrapper<EStudent> wrapper = new QueryWrapper<>();
        wrapper.eq("s.is_deleted", '0');
        if (ObjectUtil.isNull(criteria)) {
            if (!SecurityUtils.getDataScopeType().equals(DataScopeEnum.ALL.getValue())) {
                wrapper.in("s.university_id", SecurityUtils.getCurrentUserDataScope());
            }
        } else {
            if (ObjectUtil.isNotNull(criteria.getId())) {
                wrapper.eq("s.id", criteria.getId());
            }
            if (ObjectUtil.isNotNull(criteria.getUserId())) {
                wrapper.eq("s.user_id", criteria.getUserId());
            }
            if (ObjectUtil.isNotNull(criteria.getUniversityId())) {
                wrapper.eq("s.university_id", criteria.getUniversityId());
            } else {
                if (!SecurityUtils.getDataScopeType().equals(DataScopeEnum.ALL.getValue())) {
                    wrapper.in("s.university_id", SecurityUtils.getCurrentUserDataScope());
                }
            }
            if (ObjectUtil.isNotNull(criteria.getName())) {
                wrapper.like("s.name", criteria.getName());
            }
            if (ObjectUtil.isNotNull(criteria.getIdCard())) {
                wrapper.like("s.id_card", criteria.getIdCard());
            }
            if (ObjectUtil.isNotNull(criteria.getCollege())) {
                wrapper.like("s.college", criteria.getCollege());
            }
            if (ObjectUtil.isNotNull(criteria.getMajor())) {
                wrapper.like("s.major", criteria.getMajor());
            }
            if (ObjectUtil.isNotNull(criteria.getStudentNum())) {
                wrapper.eq("s.student_num", criteria.getStudentNum());
            }
            if (ObjectUtil.isNotNull(criteria.getAdmissionNum())) {
                wrapper.eq("s.admission_num", criteria.getAdmissionNum());
            }
            if (ObjectUtil.isNotNull(criteria.getEnrollmentYear())) {
                wrapper.eq("s.enrollment_year", criteria.getEnrollmentYear());
            }
            if (ObjectUtil.isNotNull(criteria.getUniversityName())) {
                wrapper.eq("d.id", criteria.getUniversityName());
            }
        }
        return wrapper;
    }


    @Override
    public void download(List<StudentDto> studentDos, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (StudentDto studentDto : studentDos) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("学生姓名", studentDto.getName());
            map.put("学生学号", studentDto.getStudentNum());
            map.put("学生身份证号", studentDto.getIdCard());
            map.put("学生准考证号", studentDto.getAdmissionNum());
            map.put("入学年度", studentDto.getEnrollmentYear());
            map.put("学院名称", studentDto.getCollege());
            map.put("学校名称", studentDto.getUniversityId());
            map.put("性别", studentDto.getSex()?"男":"女");
            list.add(map);
        }
        FileUtils.downloadExcel(list, response);
    }


    /**
     * Description:
     * 根据criteria条件和isQuery查询
     * todo isQuery的作用
     *
     * @param criteria : Dept查询条件
     * @param isQuery :  是否判断当前用户数据权限
     * @return java.util.List<marchsoft.modules.system.entity.dto.DeptDTO>
     * @author yx
     * @date 2020/11/26 15:45
     **/
    @Override
    public List<StudentDto> queryAll(EStudentQueryCriteria criteria, Boolean isQuery) {
        List<EStudent> students = this.eStudentMapper.selectList(analysisQueryCriteria(criteria));
        return studentMapStruct.toDto(students);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addExcel(List<StudentExcel> cachedDataList) {
        List<EStudent> excel = studentMapStruct.excel(cachedDataList);
        for (EStudent eStudent : excel){
            this.addStudent(eStudent);
        }
    }

    private LambdaQueryWrapper<EStudent> analysisQueryCriteria(EStudentQueryCriteria criteria) {
        LambdaQueryWrapper<EStudent> wrapper = new LambdaQueryWrapper<>();
        return wrapper;
    }



}


